TODO — API base paths behind Nginx (/{client}/api/...)
Problem: Services assume they are mounted at / (root). Nginx exposes them under a client prefix, e.g. /gqc/api/fastapi/. Swagger, OpenAPI, redirects, and some SDK default URLs break because they reference absolute paths like /openapi.json instead of /gqc/api/fastapi/openapi.json.
Status: Partial — nginx CopilotKit preflight redirect fixed; FastAPI ROOT_PATH env added; Copilot/Next.js base path not done.
Symptom checklist
| URL | Expected | Actual (today) |
|---|---|---|
http://<ip>/gqc/api/fastapi/docs | Swagger loads spec | Fetches /openapi.json → 404 |
http://<ip>/gqc/api/fastapi/openapi.json | 200 | 404 until ROOT_PATH set |
POST http://<ip>/gqc/api/copilotkit | 200 / SSE | Was 301 → CORS preflight fail (fixed in nginx) |
Direct http://127.0.0.1:8001/docs | Works | Must still work when ROOT_PATH unset |
Architecture
Browser → Nginx /gqc/api/fastapi/docs → strip prefix → FastAPI /docs
Swagger HTML references openapi.json using app.root_path
Browser → Nginx /gqc/api/fastapi/openapi.json → FastAPI /openapi.json
Each service needs both:
- Nginx — strip public prefix before upstream (already done).
- App — know the public prefix so generated links and redirects are correct.
Per-service work
1. dwd-api-fastapi (FastAPI / Uvicorn)
| Task | Status |
|---|---|
Read ROOT_PATH env and rewrite Swagger/ReDoc to load {ROOT_PATH}/openapi.json | Done (main.py) |
Set ROOT_PATH=/gqc/api/fastapi in /etc/dwd-api-fastapi/dwd-api-fastapi.env | TODO on server |
Rebuild image after pulling code (ROOT_PATH env alone is not enough without the Swagger fix) | TODO on server |
Verify /docs, /redoc, /openapi.json via nginx after redeploy | TODO |
Note: FastAPI(root_path=...) updates the OpenAPI servers list but does not fix Swagger UI — the docs page uses ASGI scope root_path, which gunicorn leaves empty. The app now injects the public OpenAPI URL into /docs when ROOT_PATH is set.
| Optional: proxy_set_header X-Forwarded-Prefix /gqc/api/fastapi in nginx (for future middleware) | Optional |
| Verify /docs, /redoc, /openapi.json via nginx after redeploy | TODO |
Server — add to /etc/dwd-api-fastapi/dwd-api-fastapi.env:
ROOT_PATH=/gqc/api/fastapi
Restart FastAPI container after editing the env file.
Do not set ROOT_PATH for Azure App Service deployments that are mounted at / (leave unset).
2. dwd-copilot-server (Next.js)
CopilotKit route is /api/copilotkit inside the container. Nginx maps /gqc/api/copilotkit → /api/copilotkit.
| Task | Status |
|---|---|
| Nginx: proxy exact path without 301 redirect (preflight-safe) | Done |
basePath in next.config.mjs if app serves pages under prefix | N/A today (API-only) |
CORS_EXTRA_ORIGINS for LAN dev origins if needed | Verify localhost:3000 (in defaults) |
| Health check URL in docs | TODO |
If we later serve Next pages under /gqc/copilot/, add:
// next.config.mjs
basePath: process.env.NEXT_PUBLIC_BASE_PATH || "",
3. dwd-mcp-fastmcp (FastMCP)
MCP protocol path is /mcp inside container; public path /gqc/api/mcp.
| Task | Status |
|---|---|
| Confirm MCP client URLs use public path in browser configs only | Done (internal uses http://dwd-mcp-fastmcp:8081/mcp) |
| MCP inspector / docs absolute URLs | Low priority |
4. Nginx templates
| Task | Status |
|---|---|
| Remove trailing-slash redirects on API paths used by browsers (CopilotKit POST/OPTIONS) | Done for copilotkit |
FastAPI /gqc/api/fastapi redirect → optional; /docs works with trailing slash on location block | OK |
Per-client copy: replace gqc + port block when adding client #2 | Documented in nginx README |
Testing
After deploy:
# OpenAPI via nginx (needs ROOT_PATH on FastAPI)
curl -sS -o /dev/null -w "%{http_code}\n" http://192.168.0.85/gqc/api/fastapi/openapi.json
# Copilot preflight — must NOT be 301
curl -sS -D- -o /dev/null -X OPTIONS http://192.168.0.85/gqc/api/copilotkit \
-H "Origin: http://localhost:3000" \
-H "Access-Control-Request-Method: POST" | head -15
# Direct container (no ROOT_PATH effect on bind mount test)
curl -sS http://127.0.0.1:8001/openapi.json | head -c 80
Browser:
-
http://192.168.0.85/gqc/api/fastapi/docsloads Swagger - CopilotKit chat from
http://localhost:3000(no CORS redirect error)